Strategies discussion
Strategies (n)
-
RAII.
-
Smart Pointers.
-
new/delete malloc/free.
-
try/catch.
-
Rust borrow checker.
Strategies (n+1) (Grouped element thinking and systems)
-
The entity has a block allocator, where all memory used by the entity uses that block allocator.
-
Sounds nice, but doesn't seem to solve the problem of memory being used in other systems.
-
-
Every frame has an arena allocator. Everything that should exist for a single frame uses that allocator.
-
Casey and Jon use this.
-
-
Use PEAK memory to know what size the block should have.
-
Very interesting.
-
Strategies (n+2)
-
ZII and Stubs as alternative ways of memory structure and error handling.
-
Casey about Stubs:
-
Stubs are just a block of zeroes.
-
"If you failed to push something into the arena, you just get a Stub back, it's all zeroed".
-
"When something comes back, just produces a Stub instead of something real, and everything still works".
-
The code doesn't check if the struct is a Stub. The code just assumes the data is something you can use and uses it.
-
For example, when using a 0 Handle, I don't return null, I just return a zeroed entity.
-
-
Stubs :
-
Stubs are minimal or fake implementations of functions, classes or modules, used mainly for testing, incremental development or simulating external dependencies.
#include <iostream> // Real function not yet implemented, we use a temporary stub int calcularImposto(float salario) { std::cout << "[STUB] Function not yet implemented." << std::endl; return 0; // Returns a fixed value to continue development } int main() { float salario = 5000; int imposto = calcularImposto(salario); std::cout << "Calculated tax: " << imposto << std::endl; return 0; } -
ZII (Zero Initialization Is Initialization)
Comparing to RAII
-
Unlike RAII, ZII does not inherently imply resource ownership or cleanup in the destructor.
-
It's about safe default values , not lifecycle management.
-
Both are part of the broader design goal of:
-
Avoiding uninitialized or unsafe state.
-
Ensuring predictable object behavior starting at construction.
-
-
Because of this shared initialization focus , they're often discussed together in contexts like:
-
C++ safety idioms.
-
Codebases transitioning from C-style to C++.
-
Embedded/safety-critical environments.
-
-
Their conceptual scopes differ, but they both leverage constructors to achieve safety and predictability, hence the mental association.
About
-
ZII is true by default for every system.
-
The way you program is by letting zero always be an acceptable value.
-
ZII is a principle that defends that variables be initialized to zero or default values as soon as they are created. This reduces the risk of accessing undefined values.
-
Main characteristics :
-
Prevents undefined behavior when accessing uninitialized variables.
-
Applicable mainly to primitive types and arrays.
-
Avoids hard-to-debug errors.
-
-
Advantages of ZII :
-
Reduces errors related to uninitialized values.
-
Ensures predictability in program behavior.
-
Useful for data structures and dynamically allocated memory.
-
Examples
#include <iostream>
class Example {
public:
int x = 0; // Zero initialization
double y = 0.0;
};
int main() {
Example e;
std::cout << "x: " << e.x << ", y: " << e.y << std::endl;
return 0;
}
int arr[10] = {}; // All elements are initialized to 0
RAII (Resource Acquisition Is Initialization)
About and Meaning
-
Bjarne Stroustrup - "RAII is the best thing the language has" .
-
"Constructors and Destructors pairs is the best feature implemented in the language".
-
"Sometimes this comes out in the name of RAII".
-
"Not the greatest name I've ever heard".
-
-
-
The phrase “Resource Acquisition Is Initialization” emphasizes that:
-
Acquiring a resource happens at the same time the object is initialized (constructed).
-
This ties the resource's lifetime to the object’s lifetime.
-
-
Why Destruction Is Implied :
-
Although destruction is not named, it's implied by C++'s object lifetime rules :
-
If the resource is acquired during initialization, and the object controls the resource.
-
Then releasing it must naturally occur when the object is destroyed.
-
-
C++ deterministic destruction ensures that destructors are called at the end of scope, enabling automatic cleanup.
-
-
Therefore, RAII relies on both construction and destruction, even if the name only mentions the construction side.
Principles
-
Associates resource acquisition (like memory, file handles, mutexes, etc.) with the construction of an object, and resource release with its destruction .
-
Scope-Based Lifetime :
-
In C++, objects declared with automatic storage duration (i.e., local stack variables) are automatically destroyed when they go out of scope.
-
-
Destructor Role :
-
The destructor is the mechanism used to release resources. Since C++ guarantees that destructors of local objects are called when the scope exits (either normally or via exception), this ensures deterministic cleanup.
-
-
Why it "implies" a destructor :
-
For RAII to work, a resource-managing object must reliably release its resource.
-
C++ destructors are guaranteed to be called when the object’s scope ends.
-
Therefore, RAII relies on this guarantee, and the destructor becomes the point where the resource is released.
-
Examples
-
Demonstration of RAII in
unique_ptrandmutex_guard.-
It's all about scope.
-
Exiting the scope calls a function automatically.
-
That's it.
-
#include <iostream>
#include <fstream>
class FileHandler {
private:
std::ofstream file;
public:
FileHandler(const std::string& filename) {
file.open(filename);
if (!file.is_open()) {
throw std::runtime_error("Failed to open the file.");
}
}
~FileHandler() {
file.close();
}
void write(const std::string& text) {
file << text << std::endl;
}
};
int main() {
try {
FileHandler fh("test.txt");
fh.write("RAII ensures the file is closed.");
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
// The FileHandler destructor closes the file automatically.
return 0;
}
Negative points
-
RAII in C++ and comparison with Odin .
-
Odin is soooo much better, wow.
-
-
Makes you allocate and deallocate simple things individually.
-
Sometimes you want to be explicit about things and just free a bunch of things at once.
-
In C++ that would require you to not use the language as it was intended in some ways.
-
In C++ you have to accept the complexity of RAII.
-
-
-
Automatic destructors make you think about failure and error handling in a bad way.
-
Unwinding the object through a destructor is not going to make the error go away. The error needs to be handled depending on the circumstance.
-
You need to think about failures and program around it.
-
In RAII you spend a lot of time writing code to handle failures that will never happen, but the same errors blow up.
-
RAII doesn't solve the problem they needed to solve.
-
Some people criticized his quote, for not making a distinction between RAII and error handling.
-
.